Spring Framework
✒️ 2025-06-30 11:36 내용 수정
Spring Framework
엔터프라이즈급 Java 어플리케이션 개발을 위한 오픈소스 경량급 프레임워크
- 참고 자료 : code blog 스프링과 스프링부트(Spring Boot) | 정의, 특징, 사용 이유, 생성 방법
- Framework : 복잡한 문제를 해결하거나 서술하는데 사용되는 기본 개념 구조다.
- 대규모 데이터 처리와 트랜잭션이 동시에 행해지는 매우 큰 환경에서도 사용할 수 있고, 개인이 사용하여 웹 어플리케이션을 개발할 수도 있다.
- 이전엔 EJB(Enterprise Java Bean)이라는 기술을 사용했지만 복잡하고 개발 비용이 많이 들어 이를 경량화한 것이 Spring이다.
JSP/Servlet과 Spring
-
JSP/Servlet
- 비즈니스 로직과 화면에 표시될 로직이 혼재되어 가독성이 떨어짐
- 반복되는 Servlet 패턴으로 인해 유사한 패턴의 Servlet이 계속 증가함
- 객체를 직접 생성(
new)하기에 강한 결합을 가져 의존성 관리가 어려움 - 설정의 복잡도가 매우 높음
-
Spring MVC
- 비즈니스 로직이 분리되어 있음(
Service등의 계층에서 담당) - IoC로 Spring이 객체를 대신 만들어 관리함
- DI를 통해 객체의 의존성을 자동으로 프레임워크가 처리
- 설정 복잡도를 낮춤
- 비즈니스 로직이 분리되어 있음(
- Spring을 사용하면 개발자가 객체 생성과 의존성 관리에 신경 쓰지 않고 핵심 비즈니스 로직에만 집중할 수 있다.
| 항목 | JSP/Servlet (MVC1/MVC2) | Spring MVC |
|---|---|---|
| 패턴 구조 | MVC1: JSP가 View와 Controller 둘 다 담당MVC2: 하나의 서블릿이 Controller 역할 후 JSP로 포워딩 | 명확한 MVC 분리 + Front‐Controller (DispatcherServlet) 패턴 적용 |
| 요청 흐름 | URL → 서블릿 → 비즈니스 로직 → JSP (forward) → 응답 | URL → DispatcherServlet → HandlerMapping → Controller → Model → ViewResolver → View → 응답 |
| 뷰(View) 처리 | JSP 내 자바 코드 포함 가능 (스크립틀릿) | JSP, Thymeleaf 등 템플릿 엔진 사용. JSP는 점차 사용 줄어듦 |
| 비즈니스 로직 위치 | 서블릿, JSP 내부에 혼합 → 유지보수 어려움 | 서블릿(DispatcherServlet)은 흐름 제어, 컨트롤러는 요청 처리, 실제 로직은 @Service 등 별도 서비스 계층에서 처리 |
| 재사용성 및 확장성 | 코드 재사용 및 확장 어려움 로직과 화면이 뒤섞임 |
AOP, DI, Bean 관리 기반 구조로 모듈화·확장성 우수 |
| 설정 방식 | XML(web.xml) + @WebServlet 애너테이션 사용 |
Java Config / XML / Spring Boot 자동 설정(@SpringBootApplication)으로 선언적 설정 |
| DI/AOP 등 지원 | 직접 객체 생성(new).POJO 활용 어려움 |
Spring IoC 컨테이너와 DI으로 의존성 자동 관리. 트랜잭션, AOP, 메시지 리소스, 이벤트 기능 등 내장 |
| 템플릿 엔진 지원 | JSP (스크립틀릿 가능) | Thymeleaf, FreeMarker, JSP 등 다양한 옵션 제공 |
| 사용성 | 소규모/단순 프로젝트에 적합하지만, 코드 유지보수 어려움 | 기업/대규모 프로젝트에 적합, 설정 많지 않아도 Spring Boot로 빠르게 시작 가능 |
특징
1. 의존성 주입(DI : Dependency Injection)
- 어떤 객체가 사용할 객체를 직접 만드는 것이 아니라 객체를 주입받아 사용하는 것
- 개발자가 설정 파일에 특정 객체가 사용할 다른 객체를 설정해두면, 어플리케이션이 동작하면서 Spring이 설정 파일을 해석해 특정 객체에게 필요한 생성자를 전달한다.
- 의존성 주입(Dependency Injection) 상세 참고.
2. 제어 역전(IoC : Inversion of Control)
- 제어의 주체가 개발자가 아닌 프레임워크
- 개발자가 아닌 Spring이 객체들 간의 의존 관계와 생명 주기 관리까지 모든 제어권을 가진다.
- 일반적으로는 개발자가
new연산자로 객체를 생성하여 직접 제어 했었으나, Spring에서는 xml 파일이나 Annotation 방식으로 Spring Container에 Bean을 등록하면 Spring이 객체를 관리한다.
3. 관심 지향 프로그래밍(AOP : Aspect Oriented Programming)
- 어플리케이션 전반에 걸쳐 적용되는 공통 기능을 비즈니스 로직으로부터 분리하는 것
- 객체 지향적으로 프로그래밍을 했음에도 로그, 트랜잭션, 성능 확인 등 공통 관심 사항 기능이 핵심 관심 사항과 중복되는 경우가 발생할 수 있다.
- 이 때 프록시 패턴을 사용하여 중복된 공통 관심 사항을 분리해낸다.
4. POJO : Plane Old Java Object
- 순수 Java만을 통해서 생성한 객체
- Java 및 Java의 스펙에 정의된 기술만 사용한다.
- 외부 기술이 아닌 순수 Java 기술만을 사용하여 객체를 만들면 특정 기술이나 환경에 종속되지 않는다.
- 객체 지향 설계를 제한 없이 적용할 수 있고, 코드가 단순해져 테스트와 디버깅이 쉬워진다.
Spring Container/IoC Container와 Bean
1. Bean
- Spring IoC Container가 관리하는 객체로, Bean들은 singleton pattern이다.
- Bean 설정과 Scope 참고.
2. Spring Container
- 여러 Bean과 애플리케이션 서비스 실행을 관리하는 구조다.
-
BeanFactory: 가장 기본 IoC 컨테이너로, Bean 생명주기 관리및 의존성 주입(DI) 기능을 제공한다.- Lazy-loading 방식(요청 받는 시점에 인스턴스 생성)을 사용한다.
- App 구동 시 bean 요청 시점에 생성한다.
- Lazy-loading 방식(요청 받는 시점에 인스턴스 생성)을 사용한다.
-
ApplicationContext: BeanFactory 확장 컨테이너다.- 별도의 설정 정보를 참고하여 IoC를 적용한 Bean의 생성 및 관계 설정 등의 제어 작업을 총괄한다.
- 객체 생성, 관계 설정, 자동 설정, AOP 지원, 이벤트 관리 등을 지원한다.
- Pre-loading 방식(즉시 인스턴스 생성)을 사용한다.
-
BeanPostProcessor: Bean 인스턴스 생성 후 초기화 전후 처리 방식을 담당하는 인터페이스다.ApplicationContext가 자동으로BeanPostProcessor내에 정의된 Bean을 감지하여 postprocessor에 등록한다.- 참고 자료 : tutorialspoint Spring Bena Post processors
Spring 프로젝트 디렉터리와 파일
공통

project-root/
├── pom.xml / build.gradle ← 빌드/라이프사이클 정의, 의존성 관리
└── src/
├── main/
│ ├── java/
│ │ └── com.example.project/ ← 시작 패키지 (주요 코드 위치)
│ │ ├── ProjectApplication.java ← @SpringBootApplication, 진입점
│ │ ├── controller/ ← @Controller / @RestController
│ │ ├── service/ ← @Service 비즈니스 로직
│ │ ├── repository/ ← @Repository, DAO 계층
│ │ ├── model/ ← Entity 또는 DTO
│ │ └── config/ ← 설정 클래스 (WebConfig 등)
│ └── resources/
│ ├── application.properties/.yml ← 환경 설정 파일
│ ├── static/ ← 정적 리소스(CSS, JS, 이미지)
│ ├── templates/ ← Thymeleaf, Mustache 등의 템플릿
│ └── messages/, META-INF/ ← 로케일, 추가 리소스
└── test/
├── java/com/example/project/ ← 단위 테스트 코드
└── resources/ ← 테스트 전용 리소스
| 이름 | 설명 |
|---|---|
| src/main/java | 서버 Java 파일 |
| src/main/resources | Java 설정 파일 및 자원 파일 |
| src/main/resources/static | 정적 자원(CSS, JS 등) |
| src/main/resources/templates | HTML, JSP 파일 등 View에 해당하는 파일 |
| application.properties | 웹 서버 설정 |
| src/test/java | 단위 테스트용 Java 파일 |
| src/test/resources | src/test/java 설정 파일 |
| pom.xml | 라이브러리 의존성 관리 |
Spring Tools 4 사용 시
- 폴더 구조에서 약간의 차이가 있어 따로 정리했다.
| 이름 | 설명 |
|---|---|
| src/main/webapp/WEB-INF/views | 외부에 공개하지 않는 HTML, JSP 등 View 파일의 저장 위치 |
| src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml | web과 관련된 Spring 설정 파일 |
| src/main/webapp/WEB-INF/spring/root-context.xml | Spring 객체 설정 파일 |
Spring 구동 순서
- 참고 자료 : 코딩하는 포로리's Spring MVC 패턴: 디테일, tadakdatak's 스프링 구동 순서/과정, MVC 구조, Front-Controller 패턴, nyyangs's SpringBoot 개념, 구조, 동작 방식
- 웹 어플리케이션이 실행되면 Tomcat(WAS)에 의해
web.xml이 실행된다. web.xml에 등록된ContextLoaderListener가 생성된다.ContextLoaderListener에서root-context.xml을 호출한다.root-context.xml에 등록된 설정대로 Spring Container가 구동 되며 Bean들이 작동한다.- 처리 후에는
DispatcherServlet이 생성되어XmlWebApplicationContext객체를 이용해servlet-context.xml을 로딩하고 해석한다. - 클라이언트가 request를 URL로 보내면 View(MVC) 에서 이를 받는다.
- 클라이언트의 request를
DispatcherServlet가 받아HandlerMapping에서 요청 처리를 담당할 Controller를 찾는다. - 적절한 Controller를 찾으면 Mapper가 정보를 다시
DispatcherServlet으로 보내고,DispatcherServlet은 해당 정보를 가지고HandlerAdapter를 호출한다. HandlerAdapter는 Controller를 통해 Service에서 비즈니스 로직으로 View에게 전달할 DTO와 DAO 정보가 저장된 Model 객체를 받는다.- Controller의 처리가 완료되면 다시
DispatcherServlet으로 View 정보를 전달한다. DispatcherServlet은 전달 받은 정보를ViewResolver에게 전달한다.ViewResolver는 View 정보에 맞는 View 객체를 찾고 응답에 필요한 데이터를 생성한다.DispatcherServlet은VeiwResolver가 처리한 결과를 클라이언트에게 응답으로 보낸다.

관련 클래스
| 클래스 | 설명 |
|---|---|
DispatcherServlet |
SpringMVC의 핵심으로 클라이언트의 HTTP 요청을 가장 먼저 받아 적절한 Controller로 보내는 역할을 하는 Servlet |
ContextLoaderListener |
SpringApplicationContext를 생성하고 로드하며, 어플리케이션 전반에 걸쳐 사용되는 Bean을 정의한 rootContext를 초기화 |
ApplicationContext |
별도의 설정 정보를 참고하여 IoC를 적용한 Bean의 생성 및 관계 설정 등의 제어 작업을 총괄함 |
ServletConfig |
DispatcherServlet이 사용할 설정을 지정 |
HandlerMapping |
요청을 처리할 Controller를 찾아주는 역할 |
RequestMappingHandlerMapping |
@RequestMapping Annotation을 기반으로 URL과 Controller 메소드를 mapping하는 Bean |
RequestMappingHandlerAdapter |
Controller 메소드의 실행을 처리하고 반환값을 적절한 HTTP 응답으로 변환 |
ViewResolver |
View의 논리적인 이름을 실제 View로 mapping |
Spring에서 제공하는 HandlerMapping의 mapping 방법
| 방법 | 설명 |
|---|---|
| BeanNameUrlHandlerMapping | Bean의 이름에 있는 URL을 HTTL 요청 URL과 비교하여 일치하는 Bean을 찾음 |
| 가장 직관적이고 사용하기 쉬움 | |
| ControllerBeanNameHandlerMapping | BeanName 방법과 유사하지만 Bean 이름을 URL 형태로 짓지 않아도 Bean 이름 앞에 자동으로 URL/ 형태로 mapping |
| ControllerClassNameHandlerMapping | Bean의 클래스 이름을 URL에 mapping |
| 클래스 이름(Controller 부분 제외)을 URL에 mapping | |
| SimpleUrlHandlerMapping | Bean의 property에 mapping 정보를 저장하며, URL과 Controller mapping 정보를 한 곳에 저장할 수 있음 |
| SimpleUrlHandlerMapping Bean을 등록해야 사용할 수 있음 | |
| DefaultAnnotationHandlerMapping | @RequestMapping Annotation을 사용해서 클래스, 메소드 단위로도 URL을 mapping |